#pragma once

#include <cstdint>
#include <iostream>
#include <vector>
using namespace std;

template <typename T>
struct global
{
    int32_t get(T t, std::vector<int32_t>& vec) const
    {
        return ref(t, vec);
    }

    int32_t& ref(T t, std::vector<int32_t>& vec) const;
};

class test
{
public:
    test();
    virtual ~test();

    test(const std::string& name)
        : _name(name) {};

    test(std::string&& name)
        : _name(std::move(name)) {};

    test(const test& other)
    {
        cout << "test(const test& other)" << endl;
        if (&other == this)
        {
            return;
        }
        this->_name = other._name;
    };

    test(test&& other)
    {
        cout << "test(test&& other)" << endl;
        if (&other != this)
        {
            this->_name = std::move(other._name);
        }
    };

    test& operator=(const test& other)
    {
        cout << "test& operator = (const test& other)" << endl;
        if (&other != this)
        {
            this->_name = other._name;
        }
        return *this;
    };

    test& operator=(test&& other)
    {
        cout << "test& operator = (test&& other)" << endl;
        if (&other != this)
        {
            this->_name = std::move(other._name);
        }
        return *this;
    };

    template <typename T>
    void f1(const T& t);

private:
    string _name;
};

const global<int> g;

template <typename T>
void test::f1(const T& t)
{
    cout << &g << endl;
}
